﻿#include "MapObject.h"
#include "../MirScenes/GameScene.h"
#include "../MirSounds/SoundManager.h"
#include "../Forms/Client.CMain.h"
#include "../MirGraphics/DXManager.h"
#include "../MirScenes/Dialogs/GroupDialog.h"

using namespace Client::MirControls;
using namespace Client::MirGraphics;
using namespace Client::MirScenes;
using namespace Client::MirSounds;
using namespace Client::MirScenes::Dialogs;
using namespace SlimDX;

namespace Client::MirObjects
{

Font *MapObject::ChatFont = new Font(Settings::FontName, 10.0F);
std::vector<MirLabel*> MapObject::LabelList;
UserObject *MapObject::User;
MapObject *MapObject::MouseObject;
MapObject *MapObject::TargetObject;
MapObject *MapObject::MagicObject;

    QueuedAction *MapObject::getNextAction() const
    {
        return ActionFeed.size() > 0 ? ActionFeed[0] : nullptr;
    }

std::vector<MirLabel*> MapObject::DamageLabelList;

    Point *MapObject::getGlobalDisplayLocationOffset() const
    {
        return new Point(0, 0);
    }

    MapObject::MapObject(unsigned int objectID)
    {
        ObjectID = objectID;

        for (int i = MapControl::Objects.size() - 1; i >= 0; i--)
        {
            MapObject *ob = MapControl::Objects[i];
            if (ob->ObjectID != ObjectID)
            {
                continue;
            }
            ob->Remove();
        }

        MapControl::Objects.push_back(this);
    }

    void MapObject::Remove()
    {
        if (MouseObject == this)
        {
            MouseObject = nullptr;
        }
        if (TargetObject == this)
        {
            TargetObject = nullptr;
        }
        if (MagicObject == this)
        {
            MagicObject = nullptr;
        }

        if (this == User->NextMagicObject)
        {
            User->ClearMagic();
        }

        MapControl::Objects.Remove(this);
        GameScene::Scene->MapControl->RemoveObject(this);

        if (ObjectID != GameScene::NPCID)
        {
            return;
        }

        GameScene::NPCID = 0;
        GameScene::Scene->NPCDialog->Hide();
    }

    void MapObject::AddBuffEffect(BuffType type)
    {
        for (int i = 0; i < Effects.size(); i++)
        {
            if (!(dynamic_cast<BuffEffect*>(Effects[i]) != nullptr))
            {
                continue;
            }
            if ((static_cast<BuffEffect*>(Effects[i]))->BuffType == type)
            {
                return;
            }
        }

        PlayerObject *ob = nullptr;

        if (getRace() == ObjectType::Player)
        {
            ob = static_cast<PlayerObject*>(this);
        }

        switch (type)
        {
            case BuffType::Fury:
                BuffEffect *tempVar = new BuffEffect(Libraries::Magic3, 190, 7, 1400, this, true, type);
                tempVar->Repeat = true;
                Effects.push_back(tempVar);
                break;
            case BuffType::ImmortalSkin:
                BuffEffect *tempVar2 = new BuffEffect(Libraries::Magic3, 570, 5, 1400, this, true, type);
                tempVar2->Repeat = true;
                Effects.push_back(tempVar2);
                break;
            case BuffType::SwiftFeet:
                if (ob != nullptr)
                {
                    ob->Sprint = true;
                }
                break;
            case BuffType::MoonLight:
            case BuffType::DarkBody:
                if (ob != nullptr)
                {
                    ob->Sneaking = true;
                }
                break;
            case BuffType::VampireShot:
                BuffEffect *tempVar3 = new BuffEffect(Libraries::Magic3, 2110, 6, 1400, this, true, type);
                tempVar3->Repeat = false;
                Effects.push_back(tempVar3);
                break;
            case BuffType::PoisonShot:
                BuffEffect *tempVar4 = new BuffEffect(Libraries::Magic3, 2310, 7, 1400, this, true, type);
                tempVar4->Repeat = false;
                Effects.push_back(tempVar4);
                break;
            case BuffType::EnergyShield:
            {
                BuffEffect *effect;

                BuffEffect *tempVar5 = new BuffEffect(Libraries::Magic2, 1880, 9, 900, this, true, type);
                tempVar5->Repeat = false;
                Effects.push_back(effect = tempVar5);
                SoundManager::PlaySound(20000 + static_cast<unsigned short>(Spell::EnergyShield) * 10 + 0);

                effect->Complete->addListener([&] (o, e)
                {
                    BuffEffect *tempVar6 = new BuffEffect(Libraries::Magic2, 1900, 2, 800, this, true, type);
                    tempVar6->Repeat = true;
                    Effects.push_back(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
                });
                break;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
            }
            case BuffType::MagicBooster:
                BuffEffect *tempVar7 = new BuffEffect(Libraries::Magic3, 90, 6, 1200, this, true, type);
                tempVar7->Repeat = true;
                Effects.push_back(tempVar7);
                break;
            case BuffType::PetEnhancer:
                BuffEffect *tempVar8 = new BuffEffect(Libraries::Magic3, 230, 6, 1200, this, true, type);
                tempVar8->Repeat = true;
                Effects.push_back(tempVar8);
                break;
            case BuffType::GameMaster:
                BuffEffect *tempVar9 = new BuffEffect(Libraries::CHumEffect[5], 0, 1, 1200, this, true, type);
                tempVar9->Repeat = true;
                Effects.push_back(tempVar9);
                break;
            case BuffType::GeneralMeowMeowShield:
                BuffEffect *tempVar10 = new BuffEffect(Libraries::Monsters[static_cast<unsigned short>(Monster::GeneralMeowMeow)], 529, 7, 700, this, true, type);
                tempVar10->Repeat = true;
                tempVar10->Light = 1;
                Effects.push_back(tempVar10);
                MirSounds::SoundManager::PlaySound(8322);
                break;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar10' statement was not added since tempVar10 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }
    }

    void MapObject::RemoveBuffEffect(BuffType type)
    {
        PlayerObject *ob = nullptr;

        if (getRace() == ObjectType::Player)
        {
            ob = static_cast<PlayerObject*>(this);
        }

        for (int i = 0; i < Effects.size(); i++)
        {
            if (!(dynamic_cast<BuffEffect*>(Effects[i]) != nullptr))
            {
                continue;
            }
            if ((static_cast<BuffEffect*>(Effects[i]))->BuffType != type)
            {
                continue;
            }
            Effects[i]->Repeat = false;
        }

        switch (type)
        {
            case BuffType::SwiftFeet:
                if (ob != nullptr)
                {
                    ob->Sprint = false;
                }
                break;
            case BuffType::MoonLight:
            case BuffType::DarkBody:
                if (ob != nullptr)
                {
                    ob->Sneaking = false;
                }
                break;
        }
    }

    Missile *MapObject::CreateProjectile(int baseIndex, MLibrary *library, bool blend, int count, int interval, int skip, int lightDistance, bool direction16, std::optional<Color*> &lightColour, unsigned int targetID)
    {
        return nullptr;
    }

    void MapObject::Chat(const std::string &text)
    {
        if (ChatLabel != nullptr && !ChatLabel->isDisposed())
        {
            ChatLabel->Dispose();
            ChatLabel = nullptr;
        }

        constexpr int chatWidth = 200;
        std::vector<std::string> chat;

        int index = 0;
        for (int i = 1; i < text.length(); i++)
        {
            if (TextRenderer::MeasureText(CMain::Graphics, text.substr(index, i - index), ChatFont)->Width > chatWidth)
            {
                chat.push_back(text.substr(index, i - index - 1));
                index = i - 1;
            }
        }
        chat.push_back(text.substr(index, text.length() - index));

        text = chat[0];
        for (int i = 1; i < chat.size(); i++)
        {
            text += StringHelper::formatSimple("\n{0}", chat[i]);
        }

        ChatLabel = new MirLabel();
        ChatLabel->setAutoSize(true);
        ChatLabel->setBackColour(Color::Transparent);
        ChatLabel->setForeColour(Color::White);
        ChatLabel->setOutLine(true);
        ChatLabel->setOutLineColour(Color::Black);
        ChatLabel->setDrawFormat(TextFormatFlags::HorizontalCenter);
        ChatLabel->setText(text);
        ChatTime = CMain::Time + 5000;
    }

    void MapObject::DrawChat()
    {
        if (ChatLabel == nullptr || ChatLabel->isDisposed())
        {
            return;
        }

        if (CMain::Time > ChatTime)
        {
            ChatLabel->Dispose();
            ChatLabel = nullptr;
            return;
        }

        ChatLabel->setForeColour(Dead ? Color::Gray : Color::White);
        Point tempVar(DisplayRectangle->X + (48 - ChatLabel->getSize()->Width) / 2, DisplayRectangle->Y - (60 + ChatLabel->getSize()->Height) - (Dead ? 35 : 0));
        ChatLabel->setLocation(&tempVar);
        ChatLabel->Draw();
    }

    void MapObject::CreateLabel()
    {
        NameLabel = nullptr;

        for (int i = 0; i < LabelList.size(); i++)
        {
            if (LabelList[i]->getText() != Name || LabelList[i]->getForeColour() != NameColour)
            {
                continue;
            }
            NameLabel = LabelList[i];
            break;
        }


        if (NameLabel != nullptr && !NameLabel->isDisposed())
        {
            return;
        }

        NameLabel = new MirLabel();
        NameLabel->setAutoSize(true);
        NameLabel->setBackColour(Color::Transparent);
        NameLabel->setForeColour(NameColour);
        NameLabel->setOutLine(true);
        NameLabel->setOutLineColour(Color::Black);
        NameLabel->setText(Name);
        NameLabel->Disposing->addListener([&] (o, e)
        {
            return LabelList.Remove(NameLabel);
        });
        LabelList.push_back(NameLabel);



    }

    void MapObject::DrawName()
    {
        CreateLabel();

        if (NameLabel == nullptr)
        {
            return;
        }

        NameLabel->setText(Name);
        Point tempVar(DisplayRectangle->X + (50 - NameLabel->getSize()->Width) / 2, DisplayRectangle->Y - (32 - NameLabel->getSize()->Height / 2) + (Dead ? 35 : 8));
        NameLabel->setLocation(&tempVar); //was 48 -
        NameLabel->Draw();
    }

    void MapObject::DrawBlend()
    {
        DXManager::SetBlend(true, 0.3F); //0.8
        Draw();
        DXManager::SetBlend(false);
    }

    void MapObject::DrawDamages()
    {
        for (int i = Damages.size() - 1; i >= 0; i--)
        {
            Damage *info = Damages[i];
            if (CMain::Time > info->ExpireTime)
            {
                info->DamageLabel->Dispose();
                Damages.erase(Damages.begin() + i);
            }
            else
            {
                info->Draw(DisplayRectangle->Location);
            }
        }
    }

    void MapObject::DrawHealth()
    {
        std::string name = Name;

        if (Name.find("(") != std::string::npos)
        {
            name = Name.substr((int)Name.find("(") + 1, Name.length() - (int)Name.find("(") - 2);
        }

        if (Dead)
        {
            return;
        }
        if (getRace() != ObjectType::Player && getRace() != ObjectType::Monster)
        {
            return;
        }

        if (CMain::Time >= HealthTime)
        {
            if (getRace() == ObjectType::Monster && !StringHelper::endsWith(Name, StringHelper::formatSimple("({0})", User->Name)) && !std::find(GroupDialog::GroupList.begin(), GroupDialog::GroupList.end(), name) != GroupDialog::GroupList.end())
            {
                return;
            }
            if (getRace() == ObjectType::Player && this != User && !std::find(GroupDialog::GroupList.begin(), GroupDialog::GroupList.end(), Name) != GroupDialog::GroupList.end())
            {
                return;
            }
            if (this == User && GroupDialog::GroupList.empty())
            {
                return;
            }
        }


        Libraries::Prguse2->Draw(0, DisplayRectangle->X + 8, DisplayRectangle->Y - 64);
        int index = 1;

        switch (getRace())
        {
            case ObjectType::Player:
                if (std::find(GroupDialog::GroupList.begin(), GroupDialog::GroupList.end(), name) != GroupDialog::GroupList.end())
                {
                    index = 10;
                }
                break;
            case ObjectType::Monster:
                if (std::find(GroupDialog::GroupList.begin(), GroupDialog::GroupList.end(), name) != GroupDialog::GroupList.end() || name == User->Name)
                {
                    index = 11;
                }
                break;
        }

        Rectangle tempVar(0, 0, static_cast<int>(32 * PercentHealth / 100.0F), 4);
        Point tempVar2(DisplayRectangle->X + 8, DisplayRectangle->Y - 64);
        Libraries::Prguse2->Draw(index, &tempVar, &tempVar2, Color::White, false);
    }

    void MapObject::DrawPoison()
    {
        unsigned char poisoncount = 0;
        if (Poison != PoisonType::None)
        {
            if (Poison::HasFlag(PoisonType::Green))
            {
                Rectangle tempVar(0, 0, 6, 6);
                Vector3 tempVar2(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar, Vector3::Zero, &tempVar2, Color::Black);
                Rectangle tempVar3(0, 0, 4, 4);
                Vector3 tempVar4(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar3, Vector3::Zero, &tempVar4, Color::Green);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Red))
            {
                Rectangle tempVar5(0, 0, 6, 6);
                Vector3 tempVar6(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar5, Vector3::Zero, &tempVar6, Color::Black);
                Rectangle tempVar7(0, 0, 4, 4);
                Vector3 tempVar8(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar7, Vector3::Zero, &tempVar8, Color::Red);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Bleeding))
            {
                Rectangle tempVar9(0, 0, 6, 6);
                Vector3 tempVar10(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar9, Vector3::Zero, &tempVar10, Color::Black);
                Rectangle tempVar11(0, 0, 4, 4);
                Vector3 tempVar12(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar11, Vector3::Zero, &tempVar12, Color::DarkRed);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Slow))
            {
                Rectangle tempVar13(0, 0, 6, 6);
                Vector3 tempVar14(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar13, Vector3::Zero, &tempVar14, Color::Black);
                Rectangle tempVar15(0, 0, 4, 4);
                Vector3 tempVar16(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar15, Vector3::Zero, &tempVar16, Color::Purple);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Stun) || Poison::HasFlag(PoisonType::Dazed))
            {
                Rectangle tempVar17(0, 0, 6, 6);
                Vector3 tempVar18(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar17, Vector3::Zero, &tempVar18, Color::Black);
                Rectangle tempVar19(0, 0, 4, 4);
                Vector3 tempVar20(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar19, Vector3::Zero, &tempVar20, Color::Yellow);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Blindness))
            {
                Rectangle tempVar21(0, 0, 6, 6);
                Vector3 tempVar22(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar21, Vector3::Zero, &tempVar22, Color::Black);
                Rectangle tempVar23(0, 0, 4, 4);
                Vector3 tempVar24(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar23, Vector3::Zero, &tempVar24, Color::MediumVioletRed);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Frozen))
            {
                Rectangle tempVar25(0, 0, 6, 6);
                Vector3 tempVar26(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar25, Vector3::Zero, &tempVar26, Color::Black);
                Rectangle tempVar27(0, 0, 4, 4);
                Vector3 tempVar28(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar27, Vector3::Zero, &tempVar28, Color::Blue);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::Paralysis) || Poison::HasFlag(PoisonType::LRParalysis))
            {
                Rectangle tempVar29(0, 0, 6, 6);
                Vector3 tempVar30(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar29, Vector3::Zero, &tempVar30, Color::Black);
                Rectangle tempVar31(0, 0, 4, 4);
                Vector3 tempVar32(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar31, Vector3::Zero, &tempVar32, Color::Gray);
                poisoncount++;
            }
            if (Poison::HasFlag(PoisonType::DelayedExplosion))
            {
                Rectangle tempVar33(0, 0, 6, 6);
                Vector3 tempVar34(static_cast<float>(DisplayRectangle->X + 7 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 21), 0.0F);
                DXManager::Sprite->Draw(DXManager::PoisonDotBackground, &tempVar33, Vector3::Zero, &tempVar34, Color::Black);
                Rectangle tempVar35(0, 0, 4, 4);
                Vector3 tempVar36(static_cast<float>(DisplayRectangle->X + 8 + (poisoncount * 5)), static_cast<float>(DisplayRectangle->Y - 20), 0.0F);
                DXManager::Sprite->Draw(DXManager::RadarTexture, &tempVar35, Vector3::Zero, &tempVar36, Color::Orange);
                poisoncount++;
            }
        }
    }
}
